package com.huawei.aiservice.utils;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.huawei.aiservice.constants.GatewayConstant;
import com.huawei.aiservice.entity.vo.InfoVo;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpCookie;
import org.springframework.http.ResponseCookie;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;

import java.util.Calendar;
import java.util.List;
import java.util.Objects;

@Component
public class JwtUtil {

    private static String jwtSecret;

    @Value(value = "${jwt.secret}")
    public void setJwtSecret(String secret) {
        jwtSecret = secret;
    }

    /**
     * 从请求头中获取token
     *
     * @param request 请求
     * @return String
     */
    public static String getTokenFromCookie(ServerHttpRequest request) {
        HttpCookie cookie = request.getCookies().getFirst(GatewayConstant.PermissionConstant.TOKEN);
        if (Objects.isNull(cookie)) {
            return "";
        }
        String token = cookie.getValue();
        if (StringUtils.isBlank(token)) {
            return "";
        }

        return token;
    }

    /**
     * 验证token的有效性
     *
     * @param token 身份令牌
     * @return token
     */
    public static String verifyToken(String token) {
        DecodedJWT jwt;
        try {
            JWTVerifier verifier = JWT.require(Algorithm.HMAC256(jwtSecret)).build();
            jwt = verifier.verify(token);
        } catch (IllegalArgumentException | JWTVerificationException e) {
            // 效验失败
            return StringUtils.EMPTY;
        }
        // 校验通过刷新token的过期时间
        return JwtUtil.refresh(jwt);
    }

    /**
     * 刷新用户的token存活时间长
     *
     * @param jwt jwt令牌
     * @return token
     */
    public static String refresh(DecodedJWT jwt) {
        Calendar expires = getExpires();
        String token = "";
        List<String> giteeAccessToken = jwt.getAudience();
        String audience = "";
        if (CollectionUtils.isNotEmpty(giteeAccessToken)) {
            audience = giteeAccessToken.get(0);
        }
        token = JWT.create()
                .withAudience(audience)
                .withExpiresAt(expires.getTime())
                .withClaim(GatewayConstant.PermissionConstant.ID,
                        jwt.getClaim(GatewayConstant.PermissionConstant.ID).as(String.class))
                .withClaim(GatewayConstant.PermissionConstant.NAME,
                        jwt.getClaim(GatewayConstant.PermissionConstant.NAME).as(String.class))
                .withClaim(GatewayConstant.PermissionConstant.LOGIN_NAME,
                        jwt.getClaim(GatewayConstant.PermissionConstant.LOGIN_NAME).as(String.class))
                .withClaim(GatewayConstant.PermissionConstant.EMAIL,
                        jwt.getClaim(GatewayConstant.PermissionConstant.EMAIL).as(String.class))
                .withClaim(GatewayConstant.PermissionConstant.AVATAR_URL,
                        jwt.getClaim(GatewayConstant.PermissionConstant.AVATAR_URL).as(String.class))
                .withClaim(GatewayConstant.PermissionConstant.LOGIN_TYPE,
                        jwt.getClaim(GatewayConstant.PermissionConstant.LOGIN_TYPE).as(String.class))
                .sign(Algorithm.HMAC256(jwtSecret));
        return token;
    }

    /**
     * 生成cookie
     *
     * @param token 身份令牌
     * @param age 过期时间
     * @return cookie
     */
    public static ResponseCookie getCookie(String token, int age) {
        // httpOnly(true), 禁止js读取; maxAge(age), 2个小时后过期
        return ResponseCookie.from("token", token).httpOnly(true).path("/api/").maxAge(age).build();
    }

    /**
     * 通过用户信息生成token
     *
     * @param infoVo 用户信息
     * @return token
     */
    public static String getToken(InfoVo infoVo) {
        Calendar expires = getExpires();
        String token = "";
        token = JWT.create()
                .withAudience(infoVo.getAccessToken())
                .withExpiresAt(expires.getTime())
                .withClaim(GatewayConstant.PermissionConstant.ID, infoVo.getId())
                .withClaim(GatewayConstant.PermissionConstant.NAME, infoVo.getName())
                .withClaim(GatewayConstant.PermissionConstant.LOGIN_NAME, infoVo.getLoginName())
                .withClaim(GatewayConstant.PermissionConstant.EMAIL, infoVo.getEmail())
                .withClaim(GatewayConstant.PermissionConstant.AVATAR_URL, infoVo.getAvatarUrl())
                .withClaim(GatewayConstant.PermissionConstant.LOGIN_TYPE, infoVo.getLoginType())
                .sign(Algorithm.HMAC256(jwtSecret));
        return token;
    }

    /**
     * 获取token存活时长
     *
     * @return 返回
     */
    public static Calendar getExpires() {
        Calendar expires = Calendar.getInstance();
        expires.add(Calendar.HOUR, 2);
//        expires.add(Calendar.MINUTE, 1);
        return expires;
    }
}
